package com.jichaoyun.sys.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jichaoyun.model.entity.FlowDay;
import com.jichaoyun.model.entity.FlowMonth;

import com.jichaoyun.model.entity.Rechargeinfo;
import com.jichaoyun.model.entity.StationInfo;

import com.jichaoyun.sys.mapper.FlowDayMapper;
import com.jichaoyun.sys.mapper.FlowMonthMapper;
import com.jichaoyun.sys.mapper.RechargeinfoMapper;
import com.jichaoyun.sys.mapper.StationInfoMapper;
import com.jichaoyun.sys.service.IFlowMonthService;
import com.jichaoyun.common.model.PagedResult;
import com.jichaoyun.common.utils.PoiExcelStyle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
* @author zhen
* @description 针对表【flow_month】的数据库操作Service实现
* @createDate 2023-11-24 10:31:07
*/
@Service
public class FlowMonthServiceImpl extends ServiceImpl<FlowMonthMapper, FlowMonth>
    implements IFlowMonthService {
    @Resource
    private StationInfoMapper stationInfoMapper;

    @Resource
    private FlowMonthMapper flowMonthMapper;

    @Resource
    private FlowDayMapper flowDayMapper;

    @Autowired
    private StationInfoServiceImpl stationInfoService;

    @Autowired
    private RechargeinfoMapper rechargeinfoMapper;


    /**
     * 获取某站点年报表
     * @param station_no
     * @param year
     * @return
     */
    @Override
    public Map<String, Object> getStationYearForm(Integer station_no, Integer year) {
        Map<String, Object> map = new LinkedHashMap<>();

        //获取每月结算的日期
        Integer accountDate = stationInfoMapper.selectById(station_no).getAccountDate();

        //判断所给的日期是否超过本月最大的天数
        LocalDate d1 = LocalDate.of(year - 1, 12, 1);
        Integer d1_max_day = d1.lengthOfMonth();
        accountDate = accountDate > d1_max_day ? d1_max_day : accountDate;

            // 获取本年度第一次结算时间
        LocalDateTime startOfYearTime = LocalDateTime.of(year - 1, 12, accountDate, 0, 0, 0);

            // 获取本年最后一次结算开始时间
        LocalDateTime endOfYearTime = LocalDateTime.of(year , 12, accountDate, 0, 1, 0);


        LambdaQueryWrapper<FlowMonth> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowMonth::getStationNo, station_no)
                .ge(FlowMonth::getRecStart, startOfYearTime)
                .le(FlowMonth::getRecStart, endOfYearTime);

        List<FlowMonth> flowMonthList = this.baseMapper.selectList(wrapper);

        if(flowMonthList!=null && flowMonthList.size() != 0){
            for (FlowMonth flowMonth : flowMonthList) {
//                System.out.println(flowMonth.toString());
                if (flowMonth.getFTotalEnd() != null) {
                    Integer month = flowMonth.getRecStart().getMonthValue();
                    map.put(month + "月", flowMonth.getFTotalEnd() - flowMonth.getFTotalStart());
                }
            }
        }
        return map;
    }

    /**
     * 导出单用户年报表
     * @param station_no
     * @param year
     * @param response
     * @throws IOException
     */
    @Override
    public void getUserYearDataExcel(Integer station_no, Integer year, HttpServletResponse response) throws IOException {
        Map<String, Object> map1 = getStationYearForm(station_no,year);

        List<Map<String,Object>> resList = new ArrayList<>();
        resList.add(map1);

        // 创建一个 ExcelWriter 把 list 数据用这个writer写出来(生成出来)
        ExcelWriter wr = ExcelUtil.getWriter( true);
        wr.write(resList, true);

        //设置excel的导出样式
        PoiExcelStyle.setStyleSet(wr,resList);

        // 把这个 excel 下载下来
        response.setContentType("application/vnd.gpenxmlfonmats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode(year + "单用户年报表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader( "Content-Disposition", "attachment;filename="+fileName+".xlsx");
        ServletOutputStream out = response.getOutputStream();
        wr.flush(out,true);
        wr.close();
        IoUtil.close(System.out);
    }

    /**
     * 获取某站点 任意区间 年报表
     * @param station_no
     * @return
     */
    @Override
    public Map<String, Object> getStationYearPeriodForm(Integer station_no, LocalDateTime start,LocalDateTime end) {
        Map<String, Object> map = new LinkedHashMap<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        //获取每天结算的小时
        LambdaQueryWrapper<FlowMonth> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowMonth::getStationNo,station_no)
                .ge(FlowMonth::getRecStart,start)
                .le(FlowMonth::getRecStart,end)
                .orderByAsc(FlowMonth::getId);

        List<FlowMonth> flowMonthList = flowMonthMapper.selectList(wrapper);

        if(flowMonthList.size()<1){
            return null;
        }

        for (int i = 0; i < flowMonthList.size(); i++) {
            FlowMonth flowMonth = flowMonthList.get(i);

            if (flowMonth == null) {
                continue; // 跳过 null 元素，或根据业务逻辑处理
            }

            if (flowMonth.getFTotalEnd() == null) {
                String data = String.format("%.2f", 0f);
                String time = flowMonth.getRecStart().plusDays(28).format(formatter);
                map.put(time, data);
            } else {
                //todo getFTotalStart为null该如何处理？先给0吧
                if(flowMonth.getFTotalStart()==null)
                {
                    flowMonth.setFTotalStart(0f);
                }
                String data = String.format("%.2f", flowMonth.getFTotalEnd() - flowMonth.getFTotalStart());
                String time = flowMonth.getRecStart().plusDays(28).format(formatter);
                map.put(time, data);
            }
        }
        return map;
    }


    /**
     * 对比上月与前月用气量
     * @param station_no
     * @return
     */
    @Override
    public Map<String, Float> getMonthSteamComparison(Integer station_no) {
        Map<String, Float> map = new HashMap<>();

        //获取当月第一天0点时刻
        LocalDateTime firstday = LocalDateTime.now().with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0);
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        LambdaQueryWrapper<FlowMonth> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowMonth::getStationNo, station_no)
                .lt(FlowMonth::getRecStart, df.format(firstday))
                .ge(FlowMonth::getRecStart, df.format(firstday.minusMonths(1)));
        FlowMonth fm1 = this.baseMapper.selectOne(wrapper);
        if (fm1 == null) {
            map.put("上月用气", 0F);
        }else{
            Float end = 0F,begin = 0F;
            if(fm1.getFTotalStart() == null) begin = 0F;
            else begin = fm1.getFTotalStart();
            if(fm1.getFTotalEnd() == null ) end = 0F;
            else end = fm1.getFTotalEnd();
            map.put("上月用气", end - begin);
        }

        LambdaQueryWrapper<FlowMonth> wrapperBefore = new LambdaQueryWrapper<>();
        wrapperBefore.eq(FlowMonth::getStationNo, station_no)
                .lt(FlowMonth::getRecStart, df.format(firstday.minusMonths(1)))
                .ge(FlowMonth::getRecStart, df.format(firstday.minusMonths(2)));
        FlowMonth fm2 = this.baseMapper.selectOne(wrapperBefore);

        if (fm2 == null) {
            map.put("前月用气", 0F);
        }else {
            Float end = 0F,begin = 0F;
            if(fm2.getFTotalStart() == null) begin = 0F;
            else begin = fm2.getFTotalStart();
            if(fm2.getFTotalEnd() == null ) end = 0F;
            else end = fm2.getFTotalEnd();
            map.put("前月用气",end - begin);
        }

        return map;
    }

    /**
     * 对比去年同上月份用气量
     * @param station_no
     * @return
     */
    @Override
    public Map<String, Float> getSameMonthSteamComparison(Integer station_no) {
        Map<String, Float> map = new HashMap<>();

        //获取当月第一天0点时刻
        LocalDateTime firstday = LocalDateTime.now().with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0);
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        LambdaQueryWrapper<FlowMonth> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowMonth::getStationNo, station_no)
                .lt(FlowMonth::getRecStart, df.format(firstday))
                .ge(FlowMonth::getRecStart, df.format(firstday.minusMonths(1)));
        FlowMonth fm1 = this.baseMapper.selectOne(wrapper);
        if (fm1 == null) {
            map.put("上月用气", 0F);
        }else{
            Float end = 0F,begin = 0F;
            if(fm1.getFTotalStart() == null) begin = 0F;
            else begin = fm1.getFTotalStart();
            if(fm1.getFTotalEnd() == null ) end = 0F;
            else end = fm1.getFTotalEnd();
            map.put("上月用气", end - begin);
        }

        LambdaQueryWrapper<FlowMonth> wrapperBefore = new LambdaQueryWrapper<>();
        wrapperBefore.eq(FlowMonth::getStationNo, station_no)
                .lt(FlowMonth::getRecStart, df.format(firstday.minusYears(1)))
                .ge(FlowMonth::getRecStart, df.format(firstday.minusYears(1).minusMonths(1)));
        FlowMonth fm2 = this.baseMapper.selectOne(wrapperBefore);

        if (fm2 == null) {
            map.put("去年同月用气", 0F);
        }else {
            Float end = 0F,begin = 0F;
            if(fm2.getFTotalStart() == null) begin = 0F;
            else begin = fm2.getFTotalStart();
            if(fm2.getFTotalEnd() == null ) end = 0F;
            else end = fm2.getFTotalEnd();
            map.put("去年同月用气",end - begin);
        }

        return map;
    }


    /**
     * 获取多用户中所有用户月报表
     * @param theMonth
     * @param pageNo
     * @return
     */
    @Override
    public PagedResult getMultiStationMonthFormPage(LocalDateTime theMonth, Integer pageNo) {
        //保存返回结果
        PagedResult pagedResult = new PagedResult();

        List<Map<String, Object>> resList = new ArrayList<>();
        //分页查找所有未被删除的站点信息表
        IPage<StationInfo> infoIPage = stationInfoService.getAllStationInfo(pageNo,10);
        List<StationInfo> stationInfos = infoIPage.getRecords();
        pagedResult.setPages((int) infoIPage.getPages());
        pagedResult.setTotal(infoIPage.getTotal());

        //查找每个用户的信息
        for (StationInfo stationInfo : stationInfos) {
            HashMap<String , Object> resMap = new HashMap<>();
            Integer station_no = stationInfo.getStationNo();
            resMap.put("用户站号",station_no);
            resMap.put("用户站名",stationInfo.getStationName());
            //获取仪表本月结算时候的总数
            Float theMonthTotal = getSettleTotalByMonth(station_no,theMonth);
            Float LastMonthTotal = getSettleTotalByMonth(station_no,theMonth.minusMonths(1));

            Boolean total_is_increased = (theMonthTotal - LastMonthTotal) > 0;
            resMap.put("仪表总数",theMonthTotal);
            resMap.put("仪表总量同比前月",theMonthTotal - LastMonthTotal);

            //本月实用
            Float theMonthFlow = getSettleFlowByMonth(station_no,theMonth);
            Float LastMonthFlow = getSettleFlowByMonth(station_no,theMonth.minusMonths(1));
            resMap.put("当月实用",theMonthFlow);
            resMap.put("流量同比前月",theMonthFlow - LastMonthFlow);

            if(stationInfo.getIsLeaf()==1){
                resMap.put("月管损",null);
                resMap.put("月管损率",null);
            }else {
                Float theLoss = getLossByMonthAndStation(station_no,theMonth);
                Float lastLoss = getLossByMonthAndStation(station_no,theMonth.minusMonths(1));
                resMap.put("月管损",theLoss);
                resMap.put("月管损同前月比较",theLoss-lastLoss);

                Float theLossRate = getLossRateByMonthAndStation(station_no,theMonth);
                Float lastLossRate = getLossRateByMonthAndStation(station_no,theMonth.minusMonths(1));
                resMap.put("月管损率",theLossRate);
                resMap.put("月管损率同前月比较",theLossRate-lastLossRate);
            }
            resList.add(resMap);
        }
        pagedResult.setRows(resList);

        return pagedResult;

    }

    /**
     * 导出多用户月报表到Excel
     * @param theMonth
     * @param response
     * @throws IOException
     */
    @Override
    public void getMultiStationMonthForm(LocalDateTime theMonth, HttpServletResponse response) throws IOException {

        List<Map<String, Object>> resList = new ArrayList<>();
        //分页查找所有未被删除的站点信息表
        List<StationInfo> stationInfos = stationInfoService.getAllStationInfo();

        //查找每个用户的信息
        for (StationInfo stationInfo : stationInfos) {
            HashMap<String , Object> resMap = new LinkedHashMap<>();
            Integer station_no = stationInfo.getStationNo();
            resMap.put("用户站号",station_no);
            resMap.put("用户站名",stationInfo.getStationName().trim());
            //获取仪表本月结算时候的总数
            Float theMonthTotal = getSettleTotalByMonth(station_no,theMonth);
            Float LastMonthTotal = getSettleTotalByMonth(station_no,theMonth.minusMonths(1));

            resMap.put("仪表总数",theMonthTotal);
            resMap.put("仪表总量同比前月",theMonthTotal - LastMonthTotal);

            //本月实用
            Float theMonthFlow = getSettleFlowByMonth(station_no,theMonth);
            Float LastMonthFlow = getSettleFlowByMonth(station_no,theMonth.minusMonths(1));
            resMap.put("当月实用",theMonthFlow);
            resMap.put("流量同比前月",theMonthFlow - LastMonthFlow);

            if(stationInfo.getIsLeaf()==1){
                resMap.put("月管损",null);
                resMap.put("月管损率",null);
            }else {
                Float theLoss = getLossByMonthAndStation(station_no,theMonth);
                Float lastLoss = getLossByMonthAndStation(station_no,theMonth.minusMonths(1));
                resMap.put("月管损",theLoss);
                resMap.put("月管损同前月比较",theLoss-lastLoss);

                Float theLossRate = getLossRateByMonthAndStation(station_no,theMonth);
                Float lastLossRate = getLossRateByMonthAndStation(station_no,theMonth.minusMonths(1));
                resMap.put("月管损率",theLossRate);
                resMap.put("月管损率同前月比较",theLossRate-lastLossRate);
            }
            resList.add(resMap);
        }

        // 创建一个 ExcelWriter 把 list 数据用这个writer写出来(生成出来)
        ExcelWriter wr = ExcelUtil.getWriter( true);
        wr.write(resList, true);

        //设置excel的导出样式
        PoiExcelStyle.setStyleSet(wr,resList);

        // 创建 DateTimeFormatter 对象，定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年M月 ");
        // 使用 DateTimeFormatter 格式化 LocalDateTime 对象
        String formattedDate = theMonth.format(formatter);

        // 把这个 excel 下载下来
        response.setContentType("application/vnd.gpenxmlfonmats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode(formattedDate+"多用户月报表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader( "Content-Disposition", "attachment;filename="+fileName+".xlsx");
        ServletOutputStream out = response.getOutputStream();
        wr.flush(out,true);
        wr.close();
        IoUtil.close(System.out);


    }

    /**
     * 根据站号查找某个站的月报表
     * @param theMonth
     * @param stationNo
     * @return
     */
    @Override
    public Map<String, Object> getMultiStationMonthFormByStation(LocalDateTime theMonth, Integer stationNo) {
        HashMap<String , Object> resMap = new HashMap<>();
        StationInfo stationInfo = stationInfoMapper.selectById(stationNo);
        Integer station_no = stationInfo.getStationNo();
        resMap.put("用户站号",station_no);
        resMap.put("用户站名",stationInfo.getStationName());
        //获取仪表本月结算时候的总数
        Float theMonthTotal = getSettleTotalByMonth(station_no,theMonth);
        Float LastMonthTotal = getSettleTotalByMonth(station_no,theMonth.minusMonths(1));

        Boolean total_is_increased = (theMonthTotal - LastMonthTotal) > 0;
        resMap.put("仪表总数",theMonthTotal);
        resMap.put("仪表总量同比前月",theMonthTotal - LastMonthTotal);

        //本月实用
        Float theMonthFlow = getSettleFlowByMonth(station_no,theMonth);
        Float LastMonthFlow = getSettleFlowByMonth(station_no,theMonth.minusMonths(1));
        resMap.put("当月实用",theMonthFlow);
        resMap.put("流量同比前月",theMonthFlow - LastMonthFlow);

        if(stationInfo.getIsLeaf()==1){
            resMap.put("月管损",null);
            resMap.put("月管损率",null);
        }else {
            Float theLoss = getLossByMonthAndStation(station_no,theMonth);
            Float lastLoss = getLossByMonthAndStation(station_no,theMonth.minusMonths(1));
            resMap.put("月管损",theLoss);
            resMap.put("月管损同前月比较",theLoss-lastLoss);

            Float theLossRate = getLossRateByMonthAndStation(station_no,theMonth);
            Float lastLossRate = getLossRateByMonthAndStation(station_no,theMonth.minusMonths(1));
            resMap.put("月管损率",theLossRate);
            resMap.put("月管损率同前月比较",theLossRate-lastLossRate);
        }

        return resMap;
    }

    /**
     * 获取多用户的年报表
     * @param theDay
     * @param pageNo
     * @return
     */
    @Override
    public PagedResult getMultiStationYearFormPage(LocalDateTime theDay, Integer pageNo) {
        //保存返回结果
        PagedResult pagedResult = new PagedResult();

        List<Map<String, Object>> resList = new ArrayList<>();
        //分页查找所有未被删除的站点信息表
        IPage<StationInfo> infoIPage = stationInfoService.getAllStationInfo(pageNo,8);
        List<StationInfo> stationInfos = infoIPage.getRecords();
        pagedResult.setTotal((int) infoIPage.getTotal());
        pagedResult.setPages((int) infoIPage.getPages());

        for (StationInfo stationInfo : stationInfos) {
            HashMap<String , Object> resMap = new HashMap<>();
            Integer station_no = stationInfo.getStationNo();
            resMap.put("用户站号",station_no);
            resMap.put("用户站名",stationInfo.getStationName());
            resMap.put("每月用汽集合",getStationYearForm(station_no,theDay.getYear()));
            resList.add(resMap);
        }
        pagedResult.setRows(resList);
        return pagedResult;
    }

    /**
     * 导出多用户年报表到Excel
     * @param theDay
     * @param response
     * @throws IOException
     */
    @Override
    public void getMultiStationYearForm(LocalDateTime theDay, HttpServletResponse response) throws IOException {

        List<Map<String, Object>> resList = new ArrayList<>();
        //分页查找所有未被删除的站点信息表
        List<StationInfo> stationInfos = stationInfoService.getAllStationInfo();

        for (StationInfo stationInfo : stationInfos) {
            HashMap<String , Object> resMap = new LinkedHashMap<>();
            Integer station_no = stationInfo.getStationNo();
            resMap.put("用户站号",station_no);
            resMap.put("用户站名",stationInfo.getStationName().trim());

            //获取每月结算的日期
            Integer accountDate = stationInfoMapper.selectById(station_no).getAccountDate();

            Integer year = theDay.getYear();
            //判断所给的日期是否超过本月最大的天数
            LocalDate d1 = LocalDate.of(year - 1, 12, 1);
            Integer d1_max_day = d1.lengthOfMonth();
            accountDate = accountDate > d1_max_day ? d1_max_day : accountDate;

            // 获取本年度最后一次结算时间
            LocalDateTime startOfYearTime = LocalDateTime.of(year - 1, 12, accountDate, 0, 0, 0);

            // 获取本年最后一次结算开始时间
            LocalDateTime endOfYearTime = LocalDateTime.of(year, 11, accountDate, 1, 0, 0);


            LambdaQueryWrapper<FlowMonth> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FlowMonth::getStationNo, station_no)
                    .ge(FlowMonth::getRecStart, startOfYearTime)
                    .le(FlowMonth::getRecStart, endOfYearTime);

            List<FlowMonth> flowMonthList = this.baseMapper.selectList(wrapper);

            for (int i=1;i<=12;i++){
                resMap.put(i+"月",0f);
            }

            for (FlowMonth flowMonth : flowMonthList) {
                if (flowMonth.getFTotalEnd() != null) {
                    Integer month = (flowMonth.getRecStart().getMonthValue() + 1) % 12;
                    resMap.put(month + "月", flowMonth.getFTotalEnd() - flowMonth.getFTotalStart());
                }
            }
            resList.add(resMap);
        }

        // 创建一个 ExcelWriter 把 list 数据用这个writer写出来(生成出来)
        ExcelWriter wr = ExcelUtil.getWriter( true);
        wr.write(resList, true);

        //设置excel的导出样式
        PoiExcelStyle.setStyleSet(wr,resList,15);

        // 创建 DateTimeFormatter 对象，定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年 ");
        // 使用 DateTimeFormatter 格式化 LocalDateTime 对象
        String formattedDate = theDay.format(formatter);

        // 把这个 excel 下载下来
        response.setContentType("application/vnd.gpenxmlfonmats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode(formattedDate+"多用户年报表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader( "Content-Disposition", "attachment;filename="+fileName+".xlsx");
        ServletOutputStream out = response.getOutputStream();
        wr.flush(out,true);
        wr.close();
        IoUtil.close(System.out);



    }



    /**
     * 修改月结算数据字段
     * @param theDay
     * @param flow
     * @return
     */
    @Override
    public Integer updateMultiStationMonthFlowSettle(LocalDateTime theDay, Float flow, Integer stationNo) {
        //获取正确的结算日期
        Integer accountDate = stationInfoMapper.selectById(stationNo).getAccountDate();
        accountDate = theDay.toLocalDate().lengthOfMonth()< accountDate? theDay.toLocalDate().lengthOfMonth():accountDate;

        LocalDateTime startTime = theDay.plusDays(accountDate-1).minusMinutes(5);
        LocalDateTime endTime = theDay.plusDays(accountDate-1).plusMinutes(5);

        LambdaQueryWrapper<FlowMonth> wp = new LambdaQueryWrapper<>();
        wp.eq(FlowMonth::getStationNo,stationNo)
                .le(FlowMonth::getRecStart,endTime)
                .ge(FlowMonth::getRecStart,startTime);
        FlowMonth flowMonth = new FlowMonth();
        flowMonth.setMonthSettleFlow(flow);

        return flowMonthMapper.update(flowMonth,wp);
    }

    /**
     * 同比月分页查找
     * @param theMonth
     * @param pageNo
     * @return
     */
    @Override
    public PagedResult getMultiStationTBMonthFormPage(LocalDateTime theMonth, Integer pageNo) {
        //保存返回结果
        PagedResult pagedResult = new PagedResult();

        List<Map<String, Object>> resList = new ArrayList<>();
        //分页查找所有未被删除的站点信息表
        IPage<StationInfo> infoIPage = stationInfoService.getAllStationInfo(pageNo,7);
        List<StationInfo> stationInfos = infoIPage.getRecords();
        pagedResult.setTotal((int) infoIPage.getTotal());
        pagedResult.setPages((int) infoIPage.getPages());

        //查找每个用户的信息
        for (StationInfo stationInfo : stationInfos) {
            HashMap<String , Object> resMap = new HashMap<>();
            Integer station_no = stationInfo.getStationNo();
            resMap.put("用户站号",station_no);
            resMap.put("用户站名",stationInfo.getStationName());

            //本月实用
            Float theMonthFlow = getSettleFlowByMonth(station_no,theMonth);
            Float LastMonthFlow = getSettleFlowByMonth(station_no,theMonth.minusMonths(1));
            Float LastYearFlow = getSettleFlowByMonth(station_no,theMonth.plusYears(1));
            resMap.put("当月用汽量",theMonthFlow);
            resMap.put("同比前月",theMonthFlow - LastMonthFlow);
            resMap.put("同比上年同月",theMonthFlow - LastYearFlow);

            //本月消费
            BigDecimal MonthlySettleMoney = getMonthlySettleMoney(station_no,theMonth);
            resMap.put("当月费用",MonthlySettleMoney);

            //本年消费
            BigDecimal yearlySettleMoney = getYearlySettleMoney(station_no,theMonth);
            resMap.put("本年累计费用",yearlySettleMoney);

            resList.add(resMap);
        }
        pagedResult.setRows(resList);

        return pagedResult;
    }

    /**
     * 多用户信息-获取月度同比分析表
     * @param theMonth
     * @param stationNo
     * @return
     */
    @Override
    public Map<String, Object> getMultiStationTBMonthFormByStation(LocalDateTime theMonth, Integer stationNo) {
        StationInfo stationInfo = stationInfoMapper.selectById(stationNo);
        Map<String , Object> resMap = new HashMap<>(7);
        Integer station_no = stationInfo.getStationNo();
        resMap.put("用户站号",station_no);
        resMap.put("用户站名",stationInfo.getStationName());

        //本月实用
        Float theMonthFlow = getSettleFlowByMonth(station_no,theMonth);
        Float LastMonthFlow = getSettleFlowByMonth(station_no,theMonth.minusMonths(1));
        Float LastYearFlow = getSettleFlowByMonth(station_no,theMonth.plusYears(1));
        resMap.put("当月用汽量",theMonthFlow);
        resMap.put("同比前月",theMonthFlow - LastMonthFlow);
        resMap.put("同比上年同月",theMonthFlow - LastYearFlow);

        //本月消费
        BigDecimal MonthlySettleMoney = getMonthlySettleMoney(station_no,theMonth);
        resMap.put("当月费用",MonthlySettleMoney);

        //本年消费
        BigDecimal yearlySettleMoney = getYearlySettleMoney(station_no,theMonth);
        resMap.put("本年累计费用",yearlySettleMoney);
        return resMap;
    }

    /**
     * 获取从某年开始 截止到某月的 累计费用
     * @param station_no
     * @param theMonth
     * @return
     */
    private BigDecimal getYearlySettleMoney(Integer station_no, LocalDateTime theMonth) {
        // 获取年费用的结算开始和结束时间
        LocalDateTime startOfDayTime =LocalDateTime.of(theMonth.toLocalDate().getYear(),1,1,0,0,0);

        LocalDateTime endOfDayTime = theMonth.plusMonths(1);

        LambdaQueryWrapper<FlowDay> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowDay::getStationNo,station_no)
                .ge(FlowDay::getRecStart,startOfDayTime)
                .le(FlowDay::getRecStart,endOfDayTime)
                .orderByAsc(FlowDay::getId);
        List<FlowDay> flowDayList = flowDayMapper.selectList(wrapper);

        if(flowDayList==null|| flowDayList.size()==0){
            return new BigDecimal(-1);
        }

        //获取这段时间充值了多少钱
        BigDecimal spend = new BigDecimal(0f);
        LocalDateTime spend_start = flowDayList.get(0).getRecStart();
        LocalDateTime spend_end = flowDayList.get(flowDayList.size()-1).getRecStart();

        LambdaQueryWrapper<Rechargeinfo> wp = new LambdaQueryWrapper<>();
        wp.eq(Rechargeinfo::getStationNo,station_no)
                .ge(Rechargeinfo::getTime,spend_start)
                .le(Rechargeinfo::getTime,spend_end);
        List<Rechargeinfo> rechargeinfoList = rechargeinfoMapper.selectList(wp);
        for (Rechargeinfo rechargeinfo : rechargeinfoList) {
            spend = spend.add(rechargeinfo.getReChargeValue());
        }

        return flowDayList.get(0).getBalance().add(spend).subtract(flowDayList.get(flowDayList.size()-1).getBalance());

    }

    /**
     * 获取月结算的money
     * @param station_no
     * @param theMonth
     * @return
     */
    private BigDecimal getMonthlySettleMoney(Integer station_no, LocalDateTime theMonth) {
        // 获取月费用的结算开始和结束时间
        LocalDateTime startOfDayTime = theMonth;
        LocalDateTime endOfDayTime = theMonth.plusMonths(1);

        LambdaQueryWrapper<FlowDay> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowDay::getStationNo,station_no)
                .ge(FlowDay::getRecStart,startOfDayTime)
                .le(FlowDay::getRecStart,endOfDayTime)
                .orderByAsc(FlowDay::getId);
        List<FlowDay> flowDayList = flowDayMapper.selectList(wrapper);

        if(flowDayList==null|| flowDayList.size()==0 ){
            return new BigDecimal(-1);
        }

        //获取这段时间充值了多少钱
        BigDecimal spend = new BigDecimal(0f);
        LocalDateTime spend_start = flowDayList.get(0).getRecStart();
        LocalDateTime spend_end = flowDayList.get(flowDayList.size()-1).getRecStart();
        LambdaQueryWrapper<Rechargeinfo> wp = new LambdaQueryWrapper<>();
        wp.eq(Rechargeinfo::getStationNo,station_no)
                .ge(Rechargeinfo::getTime,spend_start)
                .le(Rechargeinfo::getTime,spend_end);
        List<Rechargeinfo> rechargeinfoList = rechargeinfoMapper.selectList(wp);
        for (Rechargeinfo rechargeinfo : rechargeinfoList) {
            spend = spend.add(rechargeinfo.getReChargeValue());
        }
        return flowDayList.get(0).getBalance().add(spend).subtract(flowDayList.get(flowDayList.size()-1).getBalance());

    }

    /**
     * zz
     * 获取某个站点的月管损率
     * @param station_no
     * @param theMonth
     * @return
     */
    private Float getLossRateByMonthAndStation(Integer station_no, LocalDateTime theMonth) {
        //获取此站点当月第0天到最后一天的流量
        Float station_flow = getSettleFlowByMonth(station_no,theMonth);
        if(station_flow==0 ||station_flow==null){
            return -1f;
        }

        //获取该分支表下的孩子节点有哪些
        LambdaQueryWrapper<StationInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StationInfo::getFatherStationNo,station_no);
        List<StationInfo> childrenList = stationInfoMapper.selectList(wrapper);

        //计算子节点的流量之和
        Float childrens_flow = 0F;
        for (StationInfo childInfo : childrenList) {
            childrens_flow += getSettleFlowByMonth(childInfo.getStationNo(),theMonth);
        }

        //四舍五入保留四位小数
        Float f = (station_flow - childrens_flow)/station_flow;
//        System.out.println(station_flow);
//        System.out.println(childrens_flow);
        return Float.valueOf(String.format("%.4f", f));
    }

    /**
     * zz
     * 获取站点的月管损
     * @param station_no
     * @param theMonth
     * @return
     */
    private Float getLossByMonthAndStation(Integer station_no, LocalDateTime theMonth) {
        //获取此站点当月第0天到最后一天的流量
        Float station_flow = getSettleFlowByMonth(station_no,theMonth);

        //获取该分支表下的孩子节点有哪些
        LambdaQueryWrapper<StationInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StationInfo::getFatherStationNo,station_no);
        List<StationInfo> childrenList = stationInfoMapper.selectList(wrapper);

        //计算子节点的流量之和
        Float childrens_flow = 0F;
        for (StationInfo childInfo : childrenList) {
            childrens_flow += getSettleFlowByMonth(childInfo.getStationNo(),theMonth);
        }

        return station_flow - childrens_flow;

    }

    /**
     * zz
     * 获取某月实际用了多少流量
     * @param station_no
     * @param theMonth
     * @return
     */
    private Float getSettleFlowByMonth(Integer station_no, LocalDateTime theMonth) {

        // 获取日报表的结算时间,前后各差1分钟，容纳结算的时候有延迟1分钟的风险误差
        LocalDateTime startOfDayTime = theMonth;
        LocalDateTime endOfDayTime = theMonth.plusMonths(1);

        LambdaQueryWrapper<FlowDay> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowDay::getStationNo,station_no)
                .ge(FlowDay::getRecStart,startOfDayTime)
                .le(FlowDay::getRecStart,endOfDayTime)
                .orderByAsc(FlowDay::getId);
        List<FlowDay> flowDayList = flowDayMapper.selectList(wrapper);

        if(flowDayList==null|| flowDayList.size()==0){
            return -1f;
        }
        return flowDayList.get(flowDayList.size()-1).getFTotalStart() - flowDayList.get(0).getFTotalStart();

    }

    /**
     * zz
     * 获取仪表本月结算时候的蒸汽总数
     *
     * @param station_no
     * @param theDay
     * @return
     */
    private Float getSettleTotalByMonth(Integer station_no, LocalDateTime theDay) {
        //获取此站点每月的结算日
        Integer accountDate = stationInfoService.getAccountDateByStation(station_no);

        accountDate = theDay.toLocalDate().lengthOfMonth()< accountDate? theDay.toLocalDate().lengthOfMonth():accountDate;

        // 获取日报表的结算时间,前后各差5分钟，容纳结算的时候有延迟5分钟的风险误差
        LocalDateTime startOfDayTime = theDay.plusDays(accountDate-1).minusMinutes(1);
        LocalDateTime endOfDayTime = theDay.plusDays(accountDate-1).plusMinutes(5);

        LambdaQueryWrapper<FlowMonth> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowMonth::getStationNo,station_no)
                .ge(FlowMonth::getRecStart,startOfDayTime)
                .le(FlowMonth::getRecStart,endOfDayTime);
        FlowMonth flowMonth = flowMonthMapper.selectOne(wrapper);
        if(flowMonth==null){
            return -1f;
        }else {
            return flowMonth.getFTotalStart();
        }
    }
}



